package com.tbit.uqbike.client.service.impl;

import com.tbit.uqbike.center.pojo.MachineStatus;
import com.tbit.uqbike.client.constant.AccountConfigExtConstant;
import com.tbit.uqbike.client.constant.MachineStateConstant;
import com.tbit.uqbike.client.dao.core.AccountConfigDao;
import com.tbit.uqbike.client.dao.core.MachineOccupyDao;
import com.tbit.uqbike.client.dao.core.StockMachineDao;
import com.tbit.uqbike.client.exception.BaseException;
import com.tbit.uqbike.client.pojo.*;
import com.tbit.uqbike.client.pojo.newEntity.AccountConfigExt;
import com.tbit.uqbike.client.service.*;
import com.tbit.uqbike.client.util.GeoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service("machineStatusService")
public class MachineStatusServiceImpl implements MachineStatusService {
    @Autowired
    private MachineService machineService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private TerPositionService terPositionService;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private MachineStatusConsumerService machineStatusConsumerService;
    @Autowired
    private MachineOccupyDao machineOccupyDao;
    @Autowired
    private AccountConfigDao accountConfigDao;
    @Autowired
    private MachineFeeService machineFeeService;
    @Autowired
    private GeoService geoService;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private ForbiddenService forbiddenService;
    @Autowired
    private StockMachineDao stockMachineDao;
    @Autowired
    private ParkMachineService parkMachineService;

    public static void main(String[] args) {
        List<Integer> occupyMachine = new ArrayList<>();
        occupyMachine.add(1);
        occupyMachine.add(2);
        Map<Integer, Integer> map = occupyMachine.stream().collect(Collectors.toMap(Integer::intValue, Integer::intValue));
        System.out.println(map);
    }

    @Override
    public MachineStatus getByMachineNO(String machineNO, Integer mapType) {
        MachineStatus machineStatus = null;

        /**查询设备*/
        Machine machine = machineService.getByMachineNO(machineNO);
        if (machine == null) {
            throw new BaseException("-30005", "车辆不存在");
        }
        /**查询设备最后状态信息*/
        List<Integer> machineIds = new ArrayList<>();
        machineIds.add(machine.getMachineId());
        List<MachineStatus> machineStatuses = machineStatusConsumerService.getByMachineIds(machineIds);
        if (machineStatuses.size() > 0) {
            machineStatus = machineStatuses.get(0);
            if (Objects.isNull(machineStatus.getLat()) || Objects.isNull(machineStatus.getLon())) {
                throw new BaseException("车辆定位异常，请先解决车辆定位问题");
            }
            /**校准*/
            if (machineStatus.getLon() != null && machineStatus.getLat() != null) {
                calibrateService.calibrateOffSet(machineStatus, mapType);
            }
            machineStatus.setFeeName("全车型");
            /**兼容计费问题*/
            AdAccountFee adAccountFee = machineFeeService.getByAccountId(machine.getAccountId(), machine.getMachineId());
            if (adAccountFee != null) {
                machineStatus.setFeeName(machineStatus.getFeeName() + "," + adAccountFee.getName());
            }
            /**获取设备借出状态*/
            Integer bikeStatus = 0;
            MachineBorrow machineBorrow = machineBorrowService.getByMachineId(machine.getMachineId());
            if (machineBorrow != null) {
                bikeStatus = 1;
            }
            machineStatus.setIsBorrow(bikeStatus);
            /**兼容设备编号返回用户码*/
            machineStatus.setMachineNO(machine.getUserCode());
            machineStatus.setMachineType(machine.getMachineType());
            /**兼容借车判断是否在区域*/
            List<Geo> geos = geoService.getByAccountId(machine.getAccountId());
            if (!geos.isEmpty() && machineStatus.getLon() != null && machineStatus.getLat() != null) {
                List<Point> points = GeoUtil.getPoints(geos.get(0).getPoints());
                Boolean isInArea = GeoUtil
                        .IsPtInPoly(new Point(machineStatus.getLon(), machineStatus.getLat()), points);
                Double distance = GeoUtil
                        .getDistance(new Point(machineStatus.getLon(), machineStatus.getLat()), points);
                Integer borrow_range = 300;
                AccountConfigExt accountConfigExt = cacheService.getAccountConfigExtByKey(machine.getAccountId(),
                        AccountConfigExtConstant.ACCOUNTCONFIG_BORROW_ALLOWRANGE);
                if (accountConfigExt != null) {
                    borrow_range = Integer.valueOf(accountConfigExt.getParamValue());
                }
                machineStatus.setInGeo(isInArea);
                machineStatus.setDistance(distance);
                if (isInArea && distance <= borrow_range) {
                    machineStatus.setNearGeo(1);
                }
            }
            ParkMachine parkMachine = parkMachineService.getByMachineId(machine.getMachineId());
            machineStatus.setInside(parkMachine == null ? 0 : parkMachine.getInside());
            boolean isForbidden = forbiddenService.checkInForbidden(machine.getUserCode(), new Point(machineStatus.getLon(), machineStatus.getLat()));
            machineStatus.setForbidden(isForbidden);
            machineStatus.setAccountId(machine.getAccountId());
        }
        return machineStatus;
    }

    @Override
    public List<MachineStatus> getNearMachine(Integer accountId, Integer adAccountId, Integer radius, Integer mapType, Double lo, Double la) {
        List<MachineStatus> machineStatuses = new ArrayList<>();
        /**查询品牌下面所有代理商id*/
        Map<Integer, Integer> accountIdMap = new HashMap<>();
        if (adAccountId != null) {
            // 如果开启了隐藏附近车辆
            AccountConfigExt hideConfig = cacheService.getAccountConfigExtByKey(adAccountId, AccountConfigExtConstant.ACCOUNTCONFIG_SHOW_MACHINE);
            if (hideConfig != null && hideConfig.getParamValue().equals("1")) {
                return machineStatuses;
            }
            accountIdMap.put(adAccountId, adAccountId);
        } else {
            List<Account> accounts = accountService.getByParentId(accountId);
            for (Account account : accounts) {
                accountIdMap.put(account.getAccountId(), account.getAccountId());
            }
        }

        // 如果前端传值则采用入参，否则读取配置值
        AccountConfigExt accountConfigExt = cacheService.getAccountConfigExtByKey(adAccountId, AccountConfigExtConstant.NEARBY_BIKE_DISPLAY_RANGE);
        if (radius == null) {
            radius = accountConfigExt == null ? 100 : Integer.parseInt(accountConfigExt.getParamValue());
        }

        /**记录自行车编号*/
        Map<Integer, Integer> bikeMap = new HashMap<>();
        if (!accountIdMap.isEmpty()) {
            /**查询附近车辆*/
            List<TerPosition> terPositions = terPositionService.getByArea(lo, la, radius);
            if (!terPositions.isEmpty()) {
                List<Integer> machineIds = new ArrayList<>();
                List<String> machineNOs = new ArrayList<>();

                for (TerPosition terPosition : terPositions) {
                    machineNOs.add(terPosition.getMachineNO());
                }

                List<Machine> machines = machineService.getFreeByMachineNOs(machineNOs);

                /**过滤非本品牌的车辆、过滤已经借出和预约的车辆*/
                if (!machines.isEmpty()) {
                    /**运维占用设备*/
                    List<Integer> occupyMachine = machineOccupyDao.getAll();
                    Map<Integer, Integer> map = occupyMachine.stream().collect(Collectors.toMap(Integer::intValue, Integer::intValue));
                    //过滤入库车辆
                    Map<Integer, Integer> stockMap = stockMachineDao.getByAccountId(adAccountId);
                    for (Machine machine : machines) {

						/*if(occupyMachine.size()>0&&occupyMachine.contains(machine.getMachineId())){
							continue;
						}*/
                        if (!occupyMachine.isEmpty() && map.containsKey(machine.getMachineId())) {
                            continue;
                        }
                        /**正常运营设备才行*/
                        if (accountIdMap.containsKey(machine.getAccountId()) && machine.getState()
                                .equals(MachineStateConstant.MACHINE_STATE_ZCYY) && !stockMap.containsKey(machine.getMachineId())) {
                            machineIds.add(machine.getMachineId());
                        }
                        if (MachineStateConstant.MACHINE_TYPE_BIKE.equals(machine.getMachineType())) {
                            bikeMap.put(machine.getMachineId(), machine.getMachineId());
                        }
                    }

                    if (!machineIds.isEmpty()) {
                        /**查询设备最后状态信息*/
                        machineStatuses.addAll(machineStatusConsumerService.getByMachineIds(machineIds));
                        for (MachineStatus machineStatus : machineStatuses) {
                            if (machineStatus != null && machineStatus.getLon() != null && machineStatus.getLat() != null) {
                                /**校准*/
                                calibrateService.calibrateOffSet(machineStatus, mapType);
                                for (Machine m : machines) {
                                    if (machineStatus.getMachineId().equals(m.getMachineId())) {
                                        machineStatus.setUserCode(m.getUserCode());
                                        machineStatus.setMachineNO(m.getMachineNO());
                                        /**兼容返回设备类型*/
                                        machineStatus.setMachineType(m.getMachineType());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        List<MachineStatus> list = new ArrayList<>();
        /**过滤低电车辆*/
        if (adAccountId != null && !machineStatuses.isEmpty()) {
            //AccountConfig accountConfig =accountConfigDao.getByAccountId(adAccountId);
            AccountConfig accountConfig = cacheService.getConfig(adAccountId);
            if (accountConfig == null) {
                return new ArrayList<>();
            }
            for (MachineStatus status : machineStatuses) {
                /**过滤低电车辆*/
                if (status.getSocPercent() > accountConfig.getBorrowSocLimit() || bikeMap.containsKey(status.getMachineId())) {
                    list.add(status);
                }
            }
        } else {
            list.addAll(machineStatuses);
        }

        return list;
        //return machineStatuses;
    }

    /**
     * 重写 getNearMachine 方法，接口优化
     *
     * @param accountId   品牌
     * @param adAccountId 区域id
     * @param radius      半径
     * @param mapType     地图类型
     * @param lo          纬度
     * @param la          经度
     * @return
     */
    @Override
    public List<MachineStatus> getNearMachineNew(Integer accountId, Integer adAccountId, Integer radius, Integer mapType, Double lo, Double la) {
        Set<Integer> accountIds = new HashSet<>();
        if (adAccountId != null) {
            // 如果开启了隐藏附近车辆
            AccountConfigExt hideConfig = cacheService.getAccountConfigExtByKey(adAccountId, AccountConfigExtConstant.ACCOUNTCONFIG_SHOW_MACHINE);
            if (hideConfig != null && hideConfig.getParamValue().equals("1")) {
                return Collections.emptyList();
            }
            accountIds.add(adAccountId);
        } else {
            List<Account> accounts = accountService.getByParentId(accountId);
            accountIds = accounts.stream().map(Account::getAccountId).collect(Collectors.toSet());
        }
        if (accountIds.isEmpty()) {
            return Collections.emptyList();
        }
        // 如果前端传值则采用入参，否则读取配置值
        if (radius == null) {
            AccountConfigExt accountConfigExt = cacheService.getAccountConfigExtByKey(adAccountId, AccountConfigExtConstant.NEARBY_BIKE_DISPLAY_RANGE);
            radius = accountConfigExt == null ? 100 : Integer.parseInt(accountConfigExt.getParamValue());
        }
        /**查询附近车辆*/
        List<TerPosition> terPositions = terPositionService.getByArea(lo, la, radius);
        if (terPositions.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> machineNOs = terPositions.stream().map(TerPosition::getMachineNO).collect(Collectors.toList());
        // 根据设备编号和区域id集合批量查询正在运营的空闲车辆，排除已借车辆、占用车辆
        //        state=3
        //        and machineNO in(${machineNOs})
        //        and accountId in (#{accountIds})
        //        and machineId not in(select machineId from machineborrow)
        //        and machineId not in(select machineId from machineoccupy)
        //        and machineId not in(select machineId from stockmachine)
        List<Machine> machines = machineService.getFreeByMachineNOs(machineNOs, accountIds);
        if (machines.isEmpty()) {
            return Collections.emptyList();
        }
        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());
        // 根据车辆id集合查询车辆状态信息,dubbo调用
        List<MachineStatus> machineStatusList = machineStatusConsumerService.getByMachineIds(machineIds);
        if (machineStatusList == null || machineStatusList.isEmpty()) {
            return Collections.emptyList();
        }
        Map<Integer, Machine> machineMaps = machines.stream().collect(Collectors.toMap(Machine::getMachineId, Function.identity(), (key1, key2) -> key2));

        machineStatusList.stream()
                .filter(machineStatus -> machineStatus != null && machineStatus.getLon() != null && machineStatus.getLat() != null)
                .forEach(machineStatus -> {
                    // 校准
                    calibrateService.calibrateOffSet(machineStatus, mapType);
                    // 兼容返回设备类型
                    Machine machine = machineMaps.get(machineStatus.getMachineId());
                    if (machine != null) {
                        machineStatus.setUserCode(machine.getUserCode());
                        machineStatus.setMachineNO(machine.getMachineNO());
                        /**兼容返回设备类型*/
                        machineStatus.setMachineType(machine.getMachineType());
                    }
                });
        // 如果没有传区域id，则不需要过滤低电量车辆
        if (adAccountId == null || machineStatusList.isEmpty()) {
            return machineStatusList;
        }
        AccountConfig accountConfig = cacheService.getConfig(adAccountId);
        if (accountConfig == null) {
            return Collections.emptyList();
        }
        return machineStatusList.stream()
                // 过滤低电车辆
                .filter(machineStatus ->
                        machineStatus.getSocPercent() > accountConfig.getBorrowSocLimit()
                                || MachineStateConstant.MACHINE_TYPE_BIKE.equals(machineStatus.getMachineType())
                )
                .collect(Collectors.toList());
    }
}  